﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Core.Common.Monitor;
using Core.Monitors;
using CQSDK;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Tool.Web.HttpHelper;
using Tool.Windows.Win32;

namespace Core.Common
{
	static class Global
	{
		#region 兼容函数
		public delegate void Cshbl(bool IsInitSuccess, bool Authorization, bool sf = true);
		public static Cshbl Csh;
		[DllImport("data\\app\\com.acgdmzy.acg\\dmzy.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
		private static extern void Initialize(string ImagePath);
		[DllImport("data\\app\\com.acgdmzy.acg\\app.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
		private static extern int _eventEnable();
		[DllImport("data\\app\\com.acgdmzy.acg\\app.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
		private static extern int _eventStartup();
		[DllImport("data\\app\\com.acgdmzy.acg\\app.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
		private static extern int Initialize(int AuthCode);
		#endregion

		#region 全局变量
		public static bool Authorization = false;
		public static CQAPP CQ;
		public static string AppDir;
		public static string BanQQ = string.Empty;
		public static bool CanUse = false;
		public static Hashtable hashTable = new Hashtable();
		public static string ImagePath = string.Empty;
		public static WebProxy Proxy;
		public static string WaitMessage = string.Empty;
		public static long Master = 0L;
		public static string Version = "0.5.5";

		public static string ServerAddressFile = "http://nt-daily.cn:8512/dmzy/";
		public static string ServerAddressAuthorization = "http://nt-daily.cn:8513/api/dmzy/";
		public static string ServerAddressWebSocket = "ws://nt-daily.cn:8516";

		#region 监控
		public static List<MonitorInfo> DynamicInfo = new List<MonitorInfo>();
		public static List<MonitorInfo> BangumiInfo = new List<MonitorInfo>();
		public static List<MonitorInfo> BiliLiveInfo = new List<MonitorInfo>();
		public static List<MonitorInfo> YtbLiveInfo = new List<MonitorInfo>();
		public static List<MonitorInfo> TweetInfo = new List<MonitorInfo>();
		public static int MonitorFrequency;
		#endregion
		#endregion

		#region 全局正则
		public static class Reg
		{
			public static Regex CQImg;
			public static Regex Ascii2d;
			public static Regex BiliGif;
			public static Regex BiliRank;
		}
		#endregion

		//初始化
		public static void Init()
		{
			InitDynamic();
			#region 一般变量

			Reg.BiliGif = new Regex("^生成gif(av|ep)(\\d+)$", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline);
			Reg.Ascii2d = new Regex("^a2d搜索(?:[\\s]*?\\[CQ:image,file=(.+)\\][\\s]*?)?", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline);
			Reg.CQImg = new Regex("\\[CQ:image,file=(.+)\\]", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline);

			#region 必要文件下载
			if (!File.Exists(AppDir + "重载.exe"))
				Task.Run(() => File.WriteAllBytes(AppDir + "重载.exe", HttpNet.Get(ServerAddressFile + "重载.exe")));
			if (!File.Exists(AppDir + "重启.exe"))
				Task.Run(() => File.WriteAllBytes(AppDir + "重启.exe", HttpNet.Get(ServerAddressFile + "重启.exe")));
			if (!File.Exists(AppDir + "gifsicle.exe"))
				Task.Run(() => File.WriteAllBytes(AppDir + "gifsicle.exe", HttpNet.Get(ServerAddressFile + "gifsicle.exe")));
			if (!File.Exists(AppDir + "dmzy.dll"))
				File.WriteAllBytes(AppDir + "dmzy.dll", HttpNet.Get(ServerAddressFile + "dmzy.dll"));
			if (!File.Exists(AppDir + "app.dll"))
				File.WriteAllBytes(AppDir + "app.dll", HttpNet.Get(ServerAddressFile + "app.dll"));
			#endregion
			#endregion

			#region 授权
			Authorization = IsAuthorization();
			Task.Run(async () =>
			{
				DateTime d = default;
				bool flag = false;
				while (CQ.应用已启用)
				{
					await Task.Delay(60000);
					bool flag2 = IsAuthorization();
					if (Authorization != flag2)
					{
						if (flag2)
						{
							Authorization = flag2;
							if (Win32Help.IniReadValue(AppDir + "通用设置.ini", "设置", "授权变更提示", "开", 255) != "关")
							{
								CQ.SendPrivateMessage(Master, "当前授权状态变更为：授权");
							}
						}
						else if (flag)
						{
							d = DateTime.Now;
						}
						else if ((DateTime.Now - d).TotalMinutes > 30.0)
						{
							Authorization = flag2;
							if (Win32Help.IniReadValue(AppDir + "通用设置.ini", "设置", "授权变更提示", "开", 255) != "关")
							{
								CQ.SendPrivateMessage(Master, "当前授权状态变更为：未授权");
							}
							flag = true;
						}
					}
					else
					{
						flag = true;
					}
				}
			});
			if (Authorization)
			{
				Task.Run(() =>
				{
					if (File.Exists(AppDir + "动态监控.txt"))
						DynamicInfo = JsonConvert.DeserializeObject<List<MonitorInfo>>(File.ReadAllText(AppDir + "动态监控.txt"));
					if (File.Exists(AppDir + "番剧监控.txt"))
						BangumiInfo = JsonConvert.DeserializeObject<List<MonitorInfo>>(File.ReadAllText(AppDir + "番剧监控.txt"));
					if (File.Exists(AppDir + "直播监控.txt"))
						BiliLiveInfo = JsonConvert.DeserializeObject<List<MonitorInfo>>(File.ReadAllText(AppDir + "直播监控.txt"));
					if (File.Exists(AppDir + "推文监控.txt"))
						TweetInfo = JsonConvert.DeserializeObject<List<MonitorInfo>>(File.ReadAllText(AppDir + "推文监控.txt"));
					if (File.Exists(AppDir + "油管监控.txt"))
						YtbLiveInfo = JsonConvert.DeserializeObject<List<MonitorInfo>>(File.ReadAllText(AppDir + "油管监控.txt"));
					foreach (var item in DynamicInfo)
					{
						if (NeedOpen(item))
						{
							BiliDynamic dynamic = new BiliDynamic(item.flag) { TimeInterval = MonitorFrequency };
							hashTable[typeof(BiliDynamic) + item.flag] = dynamic;
							dynamic.Start();
						}
					}
					foreach (var item in BangumiInfo)
					{
						if (NeedOpen(item))
						{
							BiliBangumi bangumi = new BiliBangumi(item.flag) { TimeInterval = MonitorFrequency };
							hashTable[typeof(BiliBangumi) + item.flag] = bangumi;
							bangumi.Start();
						}
					}
					foreach (var item in BiliLiveInfo)
					{
						if (NeedOpen(item))
						{
							BiliLive live = new BiliLive(item.flag) { TimeInterval = MonitorFrequency };
							hashTable[typeof(BiliLive) + item.flag] = live;
							live.Start();
						}
					}
					foreach (var item in TweetInfo)
					{
						if (NeedOpen(item))
						{
							TweeterMonitor tweet = new TweeterMonitor(item.flag) { TimeInterval = MonitorFrequency };
							hashTable[typeof(TweeterMonitor) + item.flag] = tweet;
							tweet.Start();
						}
					}
					YoutubeLive.key = Win32Help.IniReadValue(AppDir + "高级设置.ini", "Google", "API_KEY", string.Empty, 255);
					foreach (var item in YtbLiveInfo)
					{
						if (NeedOpen(item))
						{
							YoutubeLive youtubeLive = new YoutubeLive(item.flag) { TimeInterval = MonitorFrequency };
							hashTable[typeof(YoutubeLive) + item.flag] = youtubeLive;
							youtubeLive.Start();
						}
					}
				});
			}
			#endregion

			#region 兼容旧版插件
			Initialize(CQ.AuthCode);
			_eventStartup();
			_eventEnable();
			try
			{
				int ptr = int.Parse(Win32Help.IniReadValue(AppDir + "通用设置.ini", "设置", "temp", "0", 255));
				if (ptr != 0)
				{
					Csh = (Marshal.GetDelegateForFunctionPointer((IntPtr)ptr, typeof(Cshbl)) as Cshbl);
					Csh(true, Authorization);
				}
				else
				{
					CQ.Log("检测到旧版插件未启用，部分功能将不可用");
				}
			}
			catch (Exception)
			{
				CQ.Log("检测到旧版插件未启用，部分功能将不可用");
			}
			#endregion

			WebSocketClient.Client.Open();
			Initialize(ImagePath);
			CanUse = true;
			CQ.Log("插件初始化完毕,授权状态：" + Authorization);
		}

		//动态设置初始化
		public static void InitDynamic()
		{
			string text = Win32Help.IniReadValue(AppDir + "通用设置.ini", "设置", "代理地址", string.Empty, 255);
			if (!string.IsNullOrWhiteSpace(text))
			{
				Proxy = new WebProxy(text);
			}
			BanQQ = Win32Help.IniReadValue(AppDir + "通用设置.ini", "设置", "黑名单", string.Empty, 255);
			WaitMessage = Win32Help.IniReadValue(AppDir + "通用设置.ini", "设置", "等待提示语", "少女祈祷中...", 255);
			long.TryParse(Win32Help.IniReadValue(AppDir + "通用设置.ini", "设置", "主人号码", "0", 255), out Master);
			MonitorFrequency = int.Parse(Win32Help.IniReadValue(AppDir + "通用设置.ini", "设置", "监控频率", "30", 255));

			Reg.BiliRank = new Regex("^" + Win32Help.IniReadValue(AppDir + "bilibili-通用.ini", "b站排行榜", "指令", "b站排行榜", 255) + "(?:\\|([0-9)]{1,2}))?(?:\\-([0-3]))?$", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline);

			HandleMsg.Authorization.Init();
		}

		public static bool NeedOpen(MonitorInfo info)
		{
			foreach (MonitorItem item in info.item)
			{
				if (item.status == 1)
				{
					return true;
				}
			}
			return false;
		}

		public static bool IsAuthorization()
		{
			string @string = Encoding.UTF8.GetString(HttpNet.Get(ServerAddressAuthorization + CQ.GetLoginQQ().ToString()));
			if (@string.Contains(CQ.GetLoginQQ().ToString()))
			{
				try
				{
					return ((DateTime.Parse(DecryptString(JObject.Parse(@string)["dateTime"].ToString())) - DateTime.Now).Seconds > 0) ? true : false;
				}
				catch (Exception)
				{
					return false;
				}
			}
			return false;
		}

		public static string DecryptString(string encrypt)
		{
			DESCryptoServiceProvider dESCryptoServiceProvider = new DESCryptoServiceProvider();
			byte[] bytes = Encoding.Unicode.GetBytes("dmzy");
			byte[] bytes2 = Encoding.Unicode.GetBytes("1234");
			dESCryptoServiceProvider.Key = bytes;
			dESCryptoServiceProvider.IV = bytes2;
			byte[] array = Convert.FromBase64String(encrypt);
			using (MemoryStream memoryStream = new MemoryStream())
			{
				using (CryptoStream cryptoStream = new CryptoStream(memoryStream, dESCryptoServiceProvider.CreateDecryptor(), CryptoStreamMode.Write))
				{
					cryptoStream.Write(array, 0, array.Length);
					cryptoStream.FlushFinalBlock();
					return Encoding.UTF8.GetString(memoryStream.ToArray());
				}
			}
		}
	}
}
